package impl

import (
	"context"
	"fmt"
	"net/http"
	"vblog/apps/user"
	"vblog/common"
)

// 用户管理
// 用户创建
func (i *impl) CreateUser(ctx context.Context, in *user.CreateUserReuqest) (*user.User, error) {
	//检查用户的参数
	if err := in.Validate(); err != nil {
		return nil, common.NewApiException(http.StatusBadRequest, err.Error())
	}
	// 使用构造函数生产一个blog对象
	ins := user.NewUser(in)
	err := ins.BuildHashedPassword()
	if err != nil {
		return nil, err
	}
	err = i.db.WithContext(ctx).Save(ins).Error
	if err != nil {
		return nil, common.NewApiException(http.StatusInternalServerError, err.Error())
	}
	return ins, nil
}

// 查询用户详情
func (i *impl) DescribeUser(ctx context.Context, in *user.DescribeUserRequest) (*user.User, error) {
	// 比对用户名密码,先要把用户对象查处来
	// 需要构造SQL查询
	query := i.db.WithContext(ctx).
		Model(&user.User{})
	switch in.DescribeBY {
	case user.DESCRIBE_BY_ID:
		//SELECT * FROM `users` WHERE id = '4' ORDER BY `users`.`id` LIMIT 1
		query = query.Where("id = ?", in.DescribeValue)
	case user.DESCRIBE_BY_NAME:
		query = query.Where("username = ?", in.DescribeValue)
	default:
		return nil, fmt.Errorf("unknow describe by")
	}
	ins := user.NewDefaultUser()
	err := query.First(ins).Error
	if err != nil {
		return nil, err
	}
	return ins, nil
}

// 用户登陆接口
func (i *impl) Login(ctx context.Context, in *user.LoginRequest) (*user.Token, error) {
	u, err := i.DescribeUser(ctx, user.NewDescribeUserRequestByName(in.Username))
	if err != nil {
		return nil, err
	}

	// 秘密校验
	err = u.CheckPassword(in.Password)
	if err != nil {
		return nil, common.NewApiException(http.StatusUnauthorized, err.Error())
	}

	// 颁发一个token给用户
	tk := user.NewToken(in.Username)
	err = i.db.Save(tk).Error
	if err != nil {
		return nil, err
	}
	return tk, nil
}

func (i *impl) Logout(ctx context.Context, in *user.LogoutRequest) error {
	// 删除用户token
	err := i.db.Where("username = ?", in.Username).Delete(&user.Token{}).Error
	if err != nil {
		fmt.Println(err)
		return err
	}
	return nil
}

// 校验用户token
func (i *impl) ValidateToken(ctx context.Context, in *user.ValidateTokenRequest) (*user.Token, error) {
	// 构造一个数据结构,用与接收数据库查询的结果
	tk := user.NewToken("")
	// 查询该Token是否是我们系统颁发的
	err := i.db.
		WithContext(ctx).
		Model(&user.Token{}).Where("access_token = ?", in.AccessToken).
		First(tk).
		Error
	if err != nil {
		return nil, err
	}
	// tk.CheckExpired()
	return tk, nil
}
